package ch.fhnw.ams.sudoku;

/**
 * Represent a single Sudoku field with a number between 0 and 9. If the number
 * is 0, the field appears for the user as empty field.
 * 
 * @author amsler
 * 
 */
public class SudokuField {
	
	private int number;
	private final int row;
	private final int column;
	private boolean isPuzzelNumber;
	private boolean isGenerated;
	private boolean isIncorrect;
	
	
	
	/**
	 * Constructs a new empty field.
	 * 
	 * @param row
	 *            the row number of {@link SudokuGrid}
	 * @param column
	 *            the column number of {@link SudokuGrid}
	 */
	public SudokuField(int row, int column) {
		this.row = row;
		this.column = column;
		number = 0;
		isPuzzelNumber = false;
		isIncorrect = false;
	}
	
	/**
	 * Constructs a new field with a number between 0 and 9.
	 * 
	 * @param row
	 *            the row number of {@link SudokuGrid}
	 * @param column
	 *            the column number of {@link SudokuGrid}
	 * @param number
	 *            the number of the field
	 * @param isPuzzelNumber
	 *            if <code>true</code> the field is a puzzle field
	 */
	public SudokuField(int row, int column, int number, boolean isPuzzelNumber) {
		if (number < 0 || number > 9) {
			throw new IllegalArgumentException("index out of bounds");
		}
		this.row = row;
		this.column = column;
		this.number = number;
		this.isPuzzelNumber = isPuzzelNumber;
	}
	
	/**
	 * Returns <code>true</code> if this field is empty.
	 * 
	 * @return <code>true</code> if this field is empty.
	 */
	public boolean isEmpty() {
		return number == 0 ? true : false;
	}
	
	/**
	 *	Resets the puzzle to the default state
	 */
	public void clear() {
		isPuzzelNumber = false;
		number = 0;
		isGenerated = false;
		isIncorrect = false;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + column;
		result = prime * result + (isPuzzelNumber ? 1231 : 1237);
		result = prime * result + number;
		result = prime * result + row;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		SudokuField other = (SudokuField) obj;
		if (column != other.column)
			return false;
		if (isPuzzelNumber != other.isPuzzelNumber)
			return false;
		if (number != other.number)
			return false;
		if (row != other.row)
			return false;
		return true;
	}
	
	/**
	 * Gets the number of this field.
	 * 
	 * @return the number of this field.
	 */
	public int getNumber() {
		return number;
	}
	
	/**
	 * Sets the number of this field.
	 * 
	 * @param the number of this field.
	 */
	public void setNumber(int number) {
		if (number < 0 || number > 9) {
			throw new IllegalArgumentException("index out of bounds");
		}
		isIncorrect = false;
		this.number = number;
	}
	
	/**
	 * Returns <code>true</code> if this field belongs to a puzzle.
	 * 
	 * @return <code>true</code> if this field belongs to a puzzle.
	 */
	public boolean isPuzzelNumber() {
		return isPuzzelNumber;
	}
	
	/**
	 * If <code>true</code> the field belongs to a puzzle.
	 * 
	 * @param isPuzzelNumber
	 *            <code>true</code> if the field belongs to a puzzle.
	 */
	public void setPuzzelNumber(boolean isPuzzelNumber) {
		this.isPuzzelNumber = isPuzzelNumber;
	}
	
	/**
	 * If <code>true</code> the number was set by {@link ISolver}
	 * 
	 * @return If <code>true</code> the number was set by {@link ISolver}
	 */
	public boolean isGenerated() {
		return isGenerated;
	}

	/**
	 * Set <code>true</code> if the field was modifyed by {@link ISolver}
	 * 
	 * @param isGenerated
	 *            <code>true</code> if the field was modifyed by {@link ISolver}
	 */
	public void setGenerated(boolean isGenerated) {
		this.isGenerated = isGenerated;
	}

	/**
	 * Deletes the number of this field
	 */
	public void delete() {
		isIncorrect = false;
		number = 0;
	}
	
	/**
	 * If <code>true</code> the field belongs to a wrong Sudoku solution
	 * 
	 * @return <code>true</code> if the field belongs to a wrong Sudoku solution
	 */
	public boolean isIncorrect() {
		return isIncorrect;
	}
	
	/**
	 * Set <code>true</code> if the field belongs to a wrong Sudoku solution
	 * 
	 * @param isIncorrect
	 *            <code>true</code> if the field belongs to a wrong Sudoku
	 *            solution
	 */
	public void setIncorrect(boolean isIncorrect) {
		this.isIncorrect = isIncorrect;
	}
	
	/**
	 * Returns the row number of {@link SudokuGrid}
	 * 
	 * @return the row number of {@link SudokuGrid}
	 */
	public int getRow() {
		return row;
	}
	
	/**
	 *  Returns the column number of {@link SudokuGrid}
	 * 
	 * @return the column number of {@link SudokuGrid}
	 */
	public int getColumn() {
		return column;
	}
	
}
